package edu.wpi.cs509.representation;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;

import org.hibernate.Session;

import edu.wpi.cs509.persistence.HibernateUtil;
import edu.wpi.cs509.persistence.PersistenceDatabase;

/**
 * This class contains user account information, including 
 * username/password.
 * @author jobeaupr
 *
 */
@Entity
@Table(name = "user_account")
public class UserAccount extends UserPair {
	/**
	 * serializable version number
	 */
	private static final long serialVersionUID = 1L;
	
	/**
	 * 'defines' for normal and admin privileges. 
	 */
	private static final int privNormalUser = 0;
	private static final int privAdminUser  = 1;
	
	/**
	 * This controls access to some functions.
	 */
	@Column(name = "privilege_level")
	private   int     privilegeLevel;	
	
	/**
	 * commonName is a nickname. 
	 */
	private String  commonName;
	

	/**
	 * UserId is a unique ID for each username.
	 */
	@Id
	@Column(name = "id")
	@GeneratedValue(strategy=GenerationType.AUTO)
	protected int  uid;
	
	/**
	 * User statistics.
	 */
	@OneToOne(cascade = CascadeType.ALL)
	protected UserStatistics stats;
	
	public UserAccount()
	{
		super();
	}
	
	/**
	 * Constructor
	 * @param username
	 * @param password
	 */
	public UserAccount(String username, String password) {
		super(username, password);
		init();
	}
	
	/**
	 * Constructor 
	 * @param pair (username/password pair class)
	 */
	public UserAccount(UserPair pair) {
		super(pair.getUsername(), pair.getPassword());
		init();
	}
	
	/**
	 * Initialize the user.
	 * 
	 * We want to update the database ONLY if this account does not exist already.
	 */
	public void init() {
		
//		if( !PersistenceDatabase.UsernameTaken(this.getUsername()) ) {
//			Session session = HibernateUtil.getSessionFactory().getCurrentSession();
//			session.beginTransaction();
//
//			uid = 0;
//			privilegeLevel = privNormalUser;
//
//			stats = new UserStatistics(this.getUsername());
//
//			session.saveOrUpdate(this);
//			session.getTransaction().commit();
//		}
//		else {
			uid = 0;
			privilegeLevel = privNormalUser;

			stats = new UserStatistics(this.getUsername());
//		}
	}
	
	/**
	 * TODO: Need some controls over which users can set 
	 * admin level privs??
	 */
	public void setAdminPrivilegeLevel() {
		
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();
        
		privilegeLevel = privAdminUser;
		
		session.saveOrUpdate(this);
		session.getTransaction().commit();
	}
	
	/**
	 * @return boolean true if priv-level is admin.
	 */
	public boolean hasAdminPrivilegeLevel() { 
		return (privilegeLevel == privAdminUser); 
	}
	
	/**
	 * Get the user id.
	 * @return int user-id.
	 */
	public int getUid() { 
		return this.uid; 
	}
	
	/**
	 * Get the user's stats.
	 * @return The statistics object for this user. 
	 */
	public UserStatistics getUserStats() {
		return stats;
	}
	
	public void setUserStats(UserStatistics stats)
	{
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();
        
		this.stats = stats;
		
		session.saveOrUpdate(this);
		session.getTransaction().commit();
	}
	
	/**
	 * Get the common name.
	 * @return String common name
	 */
	@Column(name = "common_name")
	public String getCommonName() { 
		return commonName; 
	}
	
	/**
	 * Set the common name.
	 * @param name
	 */
	public void setCommonName(String name) { 
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();
        
		this.commonName = name; 
		
		session.saveOrUpdate(this);
		session.getTransaction().commit();
	}

	/**
	 * Check if the password matches.
	 * @param pw
	 * @return true -- good password
	 */
	public boolean passwordMatch(String pw) {
		return validatePassword(pw);
	}
	
	public boolean canPlay() {
		if (privilegeLevel > 1)
			return true;
		else
			return false;
	}
}